<script lang="ts" setup>
import { PropType } from 'vue'
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
import { i18nChangeLanguage, IDomEditor, IEditorConfig, Boot, IToolbarConfig, DomEditor } from '@wangeditor/editor'
import { propTypes } from '@/utils/propTypes'
import { isNumber } from '@/utils/is'
import { ElMessage } from 'element-plus'
import { useLocaleStore } from '@/store/modules/locale'
import { getRefreshToken, getTenantId } from '@/utils/auth'
import { getUploadUrl } from '@/components/UploadFile/src/useUpload'
import attachmentModule from '@wangeditor/plugin-upload-attachment'
import formulaModule from '@wangeditor/plugin-formula'
import kityFormula from "./plugin/kityformula"
import myscriptMath from "./plugin/myscriptMath"
import { useAppStore } from '@/store/modules/app'
const appStore = useAppStore()

if (!appStore.getIsRegisterModule) {
	Boot.registerModule(formulaModule);
	Boot.registerMenu(kityFormula);
	Boot.registerMenu(myscriptMath);
	appStore.setIsRegisterModule(true)
}
defineOptions({ name: 'Editor' })

type InsertFnType = (url: string, alt: string, href: string) => void

const localeStore = useLocaleStore()

const currentLocale = computed(() => localeStore.getCurrentLocale)

i18nChangeLanguage(unref(currentLocale).lang)

const props = defineProps({
	editorId: propTypes.string.def('wangeEditor-1'),
	height: propTypes.oneOfType([Number, String]).def('500px'),
	editorConfig: {
		type: Object as PropType<Partial<IEditorConfig>>,
		default: () => undefined
	},
	toolbarConfig: {
		type: Object as PropType<Partial<IToolbarConfig>>,
		default: () => undefined
	},
	readonly: propTypes.bool.def(false),
	modelValue: propTypes.string.def('')
})

const emit = defineEmits(['change', 'update:modelValue'])

// 编辑器实例，必须用 shallowRef
const editorRef = shallowRef<IDomEditor>()
const valueHtml = ref('')

watch(
	() => props.modelValue,
	(val: string) => {
		if (val === unref(valueHtml)) return
		valueHtml.value = val
	},
	{
		immediate: true
	}
)

// 监听
watch(
	() => valueHtml.value,
	(val: string) => {
		emit('update:modelValue', val)
	}
)

const handleCreated = (editor: IDomEditor) => {
	editorRef.value = editor
	if (!editor.getAllMenuKeys()?.includes("uploadAttachment")) {
		Boot.registerModule(attachmentModule)
	}
}

// 编辑器配置
const editorConfig = computed((): IEditorConfig => {
	return Object.assign(
		{
			placeholder: '请输入内容...',
			readOnly: props.readonly,
			customAlert: (s: string, t: string) => {
				switch (t) {
					case 'success':
						ElMessage.success(s)
						break
					case 'info':
						ElMessage.info(s)
						break
					case 'warning':
						ElMessage.warning(s)
						break
					case 'error':
						ElMessage.error(s)
						break
					default:
						ElMessage.info(s)
						break
				}
			},
			autoFocus: false,
			scroll: true,
			hoverbarKeys: {
				attachment: {
					menuKeys: ['downloadAttachment'], // “下载附件”菜单
				},
				insertFormula: {
					menuKeys: ['insertFormula'], // “公式”菜单
				},
				kityFormula: {
					menuKeys: ['kityFormula'], // “公式”菜单
				},
				myscriptMath: {
					menuKeys: ['myscriptMath'], // “公式”菜单
				},
			},
			MENU_CONF: {
				// “上传附件”菜单的配置
				['uploadAttachment']: {
					server: getUploadUrl(),// 服务端地址
					timeout: 5 * 1000, // 5s
					fieldName: 'file',
					metaWithUrl: true, // meta 拼接到 url 上
					headers: {
						Accept: '*',
						Authorization: 'Bearer ' + getRefreshToken(), // 使用 getRefreshToken() 方法，而不使用 getAccessToken() 方法的原因：Editor 无法方便的刷新访问令牌
						'tenant-id': getTenantId()
					},
					maxFileSize: 10 * 1024 * 1024, // 10M
					onBeforeUpload(file: File) {
						console.log('onBeforeUpload', file)
						return file // 上传 file 文件
						// return false // 会阻止上传
					},
					onProgress(progress: number) {
						console.log('onProgress', progress)
					},
					onSuccess(file: File, res: any) {
						console.log('onSuccess', file, res)
					},
					onFailed(file: File, res: any) {
						alert(res.message)
						console.log('onFailed', file, res)
					},
					onError(file: File, err: Error, res: any) {
						alert(err.message)
						console.error('onError', file, err, res)
					},

					// // 上传成功后，用户自定义插入文件
					customInsert(res: any, file: File, insertFn: Function) {
						console.log('customInsert', res)
						let code = res.code
						let url = res.data
						if (code != 0) throw new Error(res.msg)
						// 插入附件到编辑器
						insertFn(file.name, url)
					},

					// // 用户自定义上传
					// customUpload(file: File, insertFn: Function) {
					//   console.log('customUpload', file)

					//   return new Promise(resolve => {
					//     // 插入一个文件，模拟异步
					//     setTimeout(() => {
					//       const src = `https://www.w3school.com.cn/i/movie.ogg`
					//       insertFn(`customUpload-${file.name}`, src)
					//       resolve('ok')
					//     }, 500)
					//   })
					// },

					// // 自定义选择
					// customBrowseAndUpload(insertFn: Function) {
					//   alert('自定义选择文件，如弹出图床')
					//   // 自己上传文件
					//   // 上传之后用 insertFn(fileName, link) 插入到编辑器
					// },

					// 插入到编辑器后的回调
					onInsertedAttachment(elem: AttachmentElement) {
						console.log('inserted attachment', elem)
					},
				},
				['uploadImage']: {
					server: getUploadUrl(),
					// 单个文件的最大体积限制，默认为 2M
					maxFileSize: 5 * 1024 * 1024,
					// 最多可上传几个文件，默认为 100
					maxNumberOfFiles: 10,
					// 选择文件时的类型限制，默认为 ['image/*'] 。如不想限制，则设置为 []
					allowedFileTypes: ['image/*'],

					// 自定义增加 http  header
					headers: {
						Accept: '*',
						Authorization: 'Bearer ' + getRefreshToken(), // 使用 getRefreshToken() 方法，而不使用 getAccessToken() 方法的原因：Editor 无法方便的刷新访问令牌
						'tenant-id': getTenantId()
					},

					// 超时时间，默认为 10 秒
					timeout: 15 * 1000, // 15 秒

					// form-data fieldName，后端接口参数名称，默认值wangeditor-uploaded-image
					fieldName: 'file',

					// 上传之前触发
					onBeforeUpload(file: File) {
						// console.log(file)
						return file
					},
					// 上传进度的回调函数
					onProgress(progress: number) {
						// progress 是 0-100 的数字
						console.log('progress', progress)
					},
					onSuccess(file: File, res: any) {
						console.log('onSuccess', file, res)
					},
					onFailed(file: File, res: any) {
						alert(res.message)
						console.log('onFailed', file, res)
					},
					onError(file: File, err: any, res: any) {
						alert(err.message)
						console.error('onError', file, err, res)
					},
					// 自定义插入图片
					customInsert(res: any, insertFn: InsertFnType) {
						insertFn(res.data, 'image', res.data)
					}
				},
				['uploadVideo']: {
					server: getUploadUrl(),
					// 单个文件的最大体积限制，默认为 10M
					maxFileSize: 10 * 1024 * 1024,
					// 最多可上传几个文件，默认为 100
					maxNumberOfFiles: 10,
					// 选择文件时的类型限制，默认为 ['video/*'] 。如不想限制，则设置为 []
					allowedFileTypes: ['video/*','audio/*'],

					// 自定义增加 http  header
					headers: {
						Accept: '*',
						Authorization: 'Bearer ' + getRefreshToken(), // 使用 getRefreshToken() 方法，而不使用 getAccessToken() 方法的原因：Editor 无法方便的刷新访问令牌
						'tenant-id': getTenantId()
					},

					// 超时时间，默认为 30 秒
					timeout: 15 * 1000, // 15 秒

					// form-data fieldName，后端接口参数名称，默认值wangeditor-uploaded-image
					fieldName: 'file',

					// 上传之前触发
					onBeforeUpload(file: File) {
						// console.log(file)
						return file
					},
					// 上传进度的回调函数
					onProgress(progress: number) {
						// progress 是 0-100 的数字
						console.log('progress', progress)
					},
					onSuccess(file: File, res: any) {
						console.log('onSuccess', file, res)
					},
					onFailed(file: File, res: any) {
						alert(res.message)
						console.log('onFailed', file, res)
					},
					onError(file: File, err: any, res: any) {
						alert(err.message)
						console.error('onError', file, err, res)
					},
					// 自定义插入图片
					customInsert(res: any, insertFn: InsertFnType) {
						insertFn(res.data, 'mp4', res.data)
					}
				}
			},
			uploadImgShowBase64: true
		},
		props.editorConfig || {}
	)
})

const toolbarConfig = computed((): Partial<IToolbarConfig> => {
  let insertKeys=[]
	console.log(props.toolbarConfig?.toolbarKeys)

	if(props.toolbarConfig?.toolbarKeys?.includes('uploadAttachment')){
		insertKeys.push('uploadAttachment')
	}
	if(props.toolbarConfig?.toolbarKeys?.includes('insertFormula')){
		insertKeys.push('insertFormula')
	}
	if(props.toolbarConfig?.toolbarKeys?.includes('kityFormula')){
		insertKeys.push('kityFormula')
	}
	return {
		// 插入哪些菜单
		insertKeys: {
			index: 0, // 自定义插入的位置
			keys: insertKeys, // “上传附件”菜单
		},
		...props.toolbarConfig || {},
		// 其他...
	}
})
const editorStyle = computed(() => {
	return {
		height: isNumber(props.height) ? `${props.height}px` : props.height
	}
})

// 回调函数
const handleChange = (editor: IDomEditor) => {
	emit('change', editor)
}

// 组件销毁时，及时销毁编辑器
onBeforeUnmount(() => {
	const editor = unref(editorRef.value)
	DomEditor.getToolbar(editor).config.insertKeys = {}
	// 销毁，并移除 editor
	editor?.destroy()
})

const getEditorRef = async (): Promise<IDomEditor> => {
	await nextTick()
	return unref(editorRef.value) as IDomEditor
}

defineExpose({
	getEditorRef
})
</script>

<template>
	<div class="border-1 border-solid border-[var(--tags-view-border-color)]">
		<!-- 工具栏 -->
		<Toolbar :editor="editorRef" :editorId="editorId" :defaultConfig="toolbarConfig"
			class="border-0 b-b-1 border-solid border-[var(--tags-view-border-color)]" />
		<!-- 编辑器 -->
		<Editor v-model="valueHtml" :defaultConfig="editorConfig" :editorId="editorId" :style="editorStyle"
			@on-change="handleChange" @on-created="handleCreated" />
	</div>
</template>

<style src="@wangeditor/editor/dist/css/style.css"></style>
